/*
 * =====================================================================================
 *
 *       Filename:  timerfd.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  02/26/2011 05:17:51 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Ken Chen (Ken), chen_kenz@emc.com
 *        Company:  EMC
 *
 * =====================================================================================
 */

#include <time.h>
#include <sys/timerfd.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
  struct itimerspec its;
  its.it_interval.tv_sec = 4;
  its.it_interval.tv_nsec = 0;

//  its.it_value.tv_sec = 2;
 // its.it_value.tv_nsec = 0;

  struct timespec now;
  clock_gettime(CLOCK_REALTIME, &now);
  its.it_value.tv_sec = now.tv_sec - 2;
  its.it_value.tv_nsec = now.tv_nsec;

  int tfd = timerfd_create(CLOCK_REALTIME, TFD_NONBLOCK);
  if(tfd == -1)
  {
    cout << "timerfd create failed\n";
    exit(-1);
  }

  if(timerfd_settime(tfd, TFD_TIMER_ABSTIME, &its, NULL) == -1)
  {
    cout << "timerfd settime failed\n";
    exit(-1);
  }

  int pfd = epoll_create(10);
  if(pfd == -1)
  {
    cout << "epoll create failed\n";
    exit(-1);
  }

  int i = 13;
  struct epoll_event event;
  memset(&event, 0, sizeof(event));
  event.events = EPOLLIN | EPOLLET;
  event.data.fd = tfd;

  if(epoll_ctl(pfd, EPOLL_CTL_ADD, tfd, &event) == -1)
  {
    cout << "epoll control failed\n";
    exit(-1);
  }

  int num = 0;
  struct epoll_event allevents[2];
  for(;;)
  {
    if((num = epoll_wait(pfd, allevents, 2, -1)) == -1)
    {
      cout << "epoll wait failed\n";
    }
    else if( num > 0 ) 
    {
      cout << "polled " << num << " timer\n";
    }
    else
    {
      cout << "polled " << num << " timer\n";
      continue;
    }

    for(int i = 0; i < num; ++i)
    {
      if(allevents[i].data.fd == tfd)
      {
        uint64_t exp;
        int sz = read(tfd, &exp, sizeof(uint64_t));
        if(sz != sizeof(uint64_t))
        {
          cout << "read error\n";
        }
        cout << exp << "\n";
      }
    }
  }

  return 0;
}

